package cn.zdq.picture_lib.loader

import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.provider.MediaStore
import android.text.TextUtils
import android.util.Log
import cn.zdq.picture_lib.R
import cn.zdq.picture_lib.app.PictureAppMaster
import cn.zdq.picture_lib.config.PictureConfig
import cn.zdq.picture_lib.config.PictureMimeType
import cn.zdq.picture_lib.config.PictureSelectionConfig
import cn.zdq.picture_lib.listener.OnQueryDataResultListener
import cn.zdq.picture_lib.model.LocalMedia
import cn.zdq.picture_lib.model.LocalMediaFolder
import cn.zdq.picture_lib.utils.MediaUtils
import cn.zdq.picture_lib.utils.SdkVersionUtils
import cn.zdq.picture_lib.utils.ValueOf
import java.util.*
import kotlin.collections.HashSet

/**
 *
 * @Description:
 * @Author: zhoudequn
 * @CreateDate: 2021/8/11 16:38
 */
class LocalMediaLoader {


    private val TAG = LocalMediaLoader::class.java.simpleName

    /**
     * 这里别用WeakReference 低端机context很容易被回收
     */
    private var config: PictureSelectionConfig = PictureSelectionConfig.getInstance()


    companion object {
        val instance by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { LocalMediaLoader() }
    }


    /**
     * 外部存储的media
     */
    private val QUERY_URI: Uri = MediaStore.Files.getContentUri("external")
    private val COLUMN_BUCKET_ID = "bucket_id"
    private val COLUMN_BUCKET_DISPLAY_NAME = "bucket_display_name"
    private val COLUMN_COUNT = "count"
    private val ORDER_BY_ID = MediaStore.Files.FileColumns._ID + " DESC"
    private val NOT_GIF_UNKNOWN = "!='image/*'"
    private val NOT_GIF = " AND (" + MediaStore.MediaColumns.MIME_TYPE + "!='image/gif' AND " +
            MediaStore.MediaColumns.MIME_TYPE + NOT_GIF_UNKNOWN + ")"
    private val GROUP_BY_BUCKET_Id = " GROUP BY (bucket_id"
    private val PROJECTION_29 = arrayOf(
        MediaStore.Files.FileColumns._ID,
        COLUMN_BUCKET_ID,
        COLUMN_BUCKET_DISPLAY_NAME,
        MediaStore.MediaColumns.MIME_TYPE
    )
    private val PROJECTION = arrayOf(
        MediaStore.Files.FileColumns._ID,
        MediaStore.MediaColumns.DATA,
        COLUMN_BUCKET_ID,
        COLUMN_BUCKET_DISPLAY_NAME,
        MediaStore.MediaColumns.MIME_TYPE,
        "COUNT(*) AS " + COLUMN_COUNT
    )

    /**
     * Media file database field
     */
    private val PROJECTION_PAGE = arrayOf(
        MediaStore.Files.FileColumns._ID,
        MediaStore.MediaColumns.DATA,
        MediaStore.MediaColumns.MIME_TYPE,
        MediaStore.MediaColumns.WIDTH,
        MediaStore.MediaColumns.HEIGHT,
        MediaStore.MediaColumns.DURATION,
        MediaStore.MediaColumns.SIZE,
        MediaStore.MediaColumns.BUCKET_DISPLAY_NAME,
        MediaStore.MediaColumns.DISPLAY_NAME,
        MediaStore.MediaColumns.BUCKET_ID,
        MediaStore.MediaColumns.DATE_ADDED
    )


    /**
     * 加载所有的media 文件夹
     * @param listener
     */
    fun loadAllMedia2(listener: OnQueryDataResultListener<LocalMediaFolder>) {
        var context: Context = PictureAppMaster.getInstance().appContext
        val cursor = context.contentResolver.query(
            QUERY_URI,
            if (SdkVersionUtils.checkedAndroid_Q()) PROJECTION_29 else PROJECTION,
            getSelection(),
            getSelectionArgs(),
            ORDER_BY_ID
        )
        var mediaFolders = mutableListOf<LocalMediaFolder>()
        try {
            if (cursor != null) {
                val count: Int = cursor.count
                var totalCount = 0
                if (count > 0) {
                    var countMap = mutableMapOf<Long, Int>()
                    if (SdkVersionUtils.checkedAndroid_Q()) {
                        //先计算
                        while (cursor.moveToNext()) {
                            val bucketId: Long =
                                cursor.getLong(cursor.getColumnIndex(COLUMN_BUCKET_ID))
                            var newCount = countMap[bucketId]
                            if (newCount == null) {
                                newCount = 1
                            } else {
                                newCount++
                            }
                            countMap[bucketId] = newCount
                        }
                    }

                    cursor.moveToFirst()
                    val hashSet = HashSet<Long>()
                    do {
                        val bucketId =
                            cursor.getLong(cursor.getColumnIndex(COLUMN_BUCKET_ID))
                        val id =
                            cursor.getLong(cursor.getColumnIndex(MediaStore.MediaColumns._ID))
                        Log.d(TAG, "zdq bucketId=" + bucketId + " id=" + id)
                        if (hashSet.contains(bucketId)) {
                            continue
                        }
                        var mediaFolder = LocalMediaFolder()
                        //下面这一条代码很恶心 导致debug看不到变量值
                        val type: String =
                            cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.MIME_TYPE))
                        val bucketDisplayName =
                            cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.BUCKET_DISPLAY_NAME))
                        mediaFolder.name = bucketDisplayName
                        mediaFolder.firstMimeType = type
                        Log.d(
                            TAG,
                            "bucketDisplayName=" + bucketDisplayName + " bucketId=" + bucketId + " type=" + type
                        )
                        var size = 0
                        if (SdkVersionUtils.checkedAndroid_Q()) {
                            size = countMap.get(bucketId) as Int
                            val id =
                                cursor.getLong(cursor.getColumnIndex(MediaStore.MediaColumns._ID))
                            Log.d(TAG, "id=" + id)
                            mediaFolder.firstImagePath = PictureMimeType.getRealPathUri(id, type)
                        } else {
                            size =
                                cursor.getInt(cursor.getColumnIndex(COLUMN_COUNT))
                            val url: String =
                                cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DATA))
                            mediaFolder.firstImagePath = url
                        }
                        mediaFolder.bucketId = bucketId
                        mediaFolder.imageNum = size
                        totalCount += size
                        mediaFolders.add(mediaFolder)
                        hashSet.add(bucketId)
                    } while (cursor.moveToNext())
                }
                //按照图片数量降序排序
                mediaFolders.sortByDescending {
                    it.imageNum
                }
                // 相机胶卷
                val allMediaFolder = LocalMediaFolder()
                allMediaFolder.imageNum = totalCount
                allMediaFolder.isChecked = true
                allMediaFolder.bucketId = -1
                if (cursor.moveToFirst()) {
                    allMediaFolder.firstImagePath =
                        if (SdkVersionUtils.checkedAndroid_Q()) getFirstUri(
                            cursor
                        ) else getFirstUrl(cursor)
                    allMediaFolder.firstMimeType =
                        getFirstCoverMimeType(cursor)
                }
                val bucketDisplayName: String =
                    if (config.chooseMode == PictureMimeType.ofAudio()) context.getString(R.string.picture_all_audio) else context.getString(
                        R.string.picture_camera_roll
                    )
                allMediaFolder.name = bucketDisplayName
                allMediaFolder.ofAllType = config.chooseMode
                allMediaFolder.isCameraFolder = true
                mediaFolders.add(0, allMediaFolder)
            }

        } catch (e: Exception) {
            e.printStackTrace()
            Log.i(TAG, "loadAllMedia Data Error: " + e.message)
        } finally {
            if (cursor != null && !cursor.isClosed()) {
                cursor.close()
            }
        }
        if (listener != null) {
            listener.onComplete(mediaFolders, 1, false)
        }
    }

    /**
     * Queries for data in the specified directory
     *
     * @param bucketId
     * @param listener
     * @return
     */
    fun loadPageMediaData(
        bucketId: Long,
        page: Int,
        listener: OnQueryDataResultListener<LocalMedia>
    ) {
        loadPageMediaData(bucketId, page, config.pageSize, config.pageSize, listener)
    }


    fun loadPageMediaData(
        bucketId: Long,
        page: Int,
        limit: Int,
        pageSize: Int,
        listener: OnQueryDataResultListener<LocalMedia>
    ) {
        var context: Context = PictureAppMaster.getInstance().appContext
        var cursor: Cursor? = null
        var results = mutableListOf<LocalMedia>()
        try {
            if (SdkVersionUtils.checkedAndroid_R()) {
                val queryArgs = MediaUtils.createQueryArgsBundle(
                    getPageSelection(bucketId), getPageSelectionArgs(bucketId),
                    limit,
                    (page - 1) * pageSize
                )
                cursor = context.contentResolver.query(
                    QUERY_URI,
                    PROJECTION_PAGE,
                    queryArgs,
                    null
                )
            } else {
                val orderBy =
                    if (page == -1) MediaStore.Files.FileColumns._ID + " DESC" else MediaStore.Files.FileColumns._ID + " DESC limit " + limit + " offset " + (page - 1) * pageSize
                cursor = context.contentResolver.query(
                    QUERY_URI,
                    PROJECTION_PAGE,
                    getPageSelection(bucketId),
                    getPageSelectionArgs(bucketId),
                    orderBy
                )
            }
            if (cursor != null) {

                if (cursor.count > 0) {
                    cursor.moveToFirst()
                    do {
                        val id =
                            cursor.getLong(cursor.getColumnIndexOrThrow(PROJECTION_PAGE[0]))
                        val absolutePath =
                            cursor.getString(
                                cursor.getColumnIndexOrThrow(
                                    PROJECTION_PAGE[1]
                                )
                            )
                        var mimeType = cursor.getString(
                            cursor.getColumnIndexOrThrow(PROJECTION_PAGE[2])
                        )
                        mimeType =
                            if (TextUtils.isEmpty(mimeType)) PictureMimeType.ofJPEG() else mimeType
                        val url =
                            if (SdkVersionUtils.checkedAndroid_Q()) PictureMimeType.getRealPathUri(
                                id,
                                mimeType
                            ) else absolutePath

                        val width: Int =
                            cursor.getInt(cursor.getColumnIndexOrThrow(PROJECTION_PAGE[3]))
                        val height: Int =
                            cursor.getInt(cursor.getColumnIndexOrThrow(PROJECTION_PAGE[4]))
                        val duration: Long =
                            cursor.getLong(cursor.getColumnIndexOrThrow(PROJECTION_PAGE[5]))
                        val size: Long =
                            cursor.getLong(cursor.getColumnIndexOrThrow(PROJECTION_PAGE[6]))
                        val folderName: String = cursor.getString(
                            cursor.getColumnIndexOrThrow(PROJECTION_PAGE[7])
                        )
                        val fileName: String = cursor.getString(
                            cursor.getColumnIndexOrThrow(PROJECTION_PAGE[8])
                        )
                        val bucket_id: Long =
                            cursor.getLong(cursor.getColumnIndexOrThrow(PROJECTION_PAGE[9]))
                        val addDate: Long =
                            cursor.getLong(cursor.getColumnIndexOrThrow(PROJECTION_PAGE[10]))
                        val image = LocalMedia.parseLocalMedia(
                            id,
                            url,
                            absolutePath,
                            fileName,
                            folderName,
                            duration,
                            config.chooseMode,
                            mimeType,
                            width,
                            height,
                            size,
                            bucket_id,
                            addDate
                        )
                        results.add(image)
                    } while (cursor.moveToNext())
                }
            }

            if (listener != null) {
                listener.onComplete(results, page, cursor?.count!! > 0)
            }

        } catch (e: Exception) {
            e.printStackTrace()

        } finally {
            if (cursor != null && !cursor.isClosed) {
                cursor.close()
            }
        }


    }

    private fun getSelection(): String {
        val fileSizeCondition: String = getFileSizeCondition()
        val queryMimeCondition: String = getQueryMimeCondition()
        when (config.chooseMode) {
            PictureConfig.TYPE_ALL ->                 // Get all, not including audio
                return getSelectionArgsForAllMediaCondition(
                    getDurationCondition(),
                    fileSizeCondition,
                    queryMimeCondition
                )
            PictureConfig.TYPE_IMAGE ->                 // Get Images
                return getSelectionArgsForImageMediaCondition(
                    queryMimeCondition,
                    fileSizeCondition
                )
            PictureConfig.TYPE_VIDEO, PictureConfig.TYPE_AUDIO ->                 // Gets the specified album directory
                return getSelectionArgsForVideoOrAudioMediaCondition(
                    queryMimeCondition,
                    fileSizeCondition
                )
        }
        return ""
    }

    private fun getFileSizeCondition(): String {
        val maxS = if (config.filterMaxFileSize == 0L) Long.MAX_VALUE else config.filterMaxFileSize

        return String.format(
            Locale.CHINA,
            "%d <%s " + MediaStore.MediaColumns.SIZE + " and " + MediaStore.MediaColumns.SIZE + " <= %d",
            Math.max(0, config.filterMinFileSize),
            if (Math.max(0, config.filterMinFileSize) == 0L) "" else "=",
            maxS
        )
    }

    private fun getQueryMimeCondition(): String {
        var stringHashSet = config.queryMimeTypeHashSet
        if (stringHashSet == null) {
            stringHashSet = HashSet()
        }
        if (!TextUtils.isEmpty(config.specifiedFormat)) {
            stringHashSet.add(config.specifiedFormat)
        }
        val stringBuilder = StringBuilder()
        val iterator: Iterator<String> = stringHashSet.iterator()
        var index = -1
        while (iterator.hasNext()) {
            val value = iterator.next()
            if (TextUtils.isEmpty(value)) {
                continue
            }
            if (config.chooseMode == PictureMimeType.ofVideo()) {
                if (value.startsWith(PictureMimeType.MIME_TYPE_PREFIX_IMAGE) || value.startsWith(
                        PictureMimeType.MIME_TYPE_PREFIX_AUDIO
                    )
                ) {
                    continue
                }
            } else if (config.chooseMode == PictureMimeType.ofImage()) {
                if (value.startsWith(PictureMimeType.MIME_TYPE_PREFIX_AUDIO) || value.startsWith(
                        PictureMimeType.MIME_TYPE_PREFIX_VIDEO
                    )
                ) {
                    continue
                }
            } else if (config.chooseMode == PictureMimeType.ofAudio()) {
                if (value.startsWith(PictureMimeType.MIME_TYPE_PREFIX_VIDEO) || value.startsWith(
                        PictureMimeType.MIME_TYPE_PREFIX_IMAGE
                    )
                ) {
                    continue
                }
            }
            index++
            stringBuilder.append(if (index == 0) " AND " else " OR ")
                .append(MediaStore.MediaColumns.MIME_TYPE).append("='").append(value).append("'")
        }
        if (config.chooseMode != PictureMimeType.ofVideo()) {
            if (!config.isGif && !stringHashSet.contains(PictureMimeType.ofGIF())) {
                stringBuilder.append(NOT_GIF)
            }
        }
        return stringBuilder.toString()
    }

    /**
     * Get video (maximum or minimum time)
     *
     * @return
     */
    private fun getDurationCondition(): String {
        val maxS =
            if (config.videoMaxSecond == 0) Long.MAX_VALUE else config.videoMaxSecond.toLong()
        return String.format(
            Locale.CHINA,
            "%d <%s " + MediaStore.MediaColumns.DURATION + " and " + MediaStore.MediaColumns.DURATION + " <= %d",
            Math.max(0.toLong(), config.videoMinSecond.toLong()),
            if (Math.max(0.toLong(), config.videoMinSecond.toLong()) == 0L) "" else "=",
            maxS
        )
    }

    /**
     * Query conditions in all modes
     *
     * @param timeCondition
     * @param sizeCondition
     * @return
     */
    private fun getSelectionArgsForAllMediaCondition(
        timeCondition: String,
        sizeCondition: String,
        queryMimeTypeOptions: String
    ): String {
        val stringBuilder = java.lang.StringBuilder()
        stringBuilder.append("(").append(MediaStore.Files.FileColumns.MEDIA_TYPE).append("=?")
            .append(queryMimeTypeOptions).append(" OR ")
            .append(MediaStore.Files.FileColumns.MEDIA_TYPE).append("=? AND ").append(timeCondition)
            .append(") AND ").append(sizeCondition)
        return if (SdkVersionUtils.checkedAndroid_Q()) {
            stringBuilder.toString()
        } else {
            stringBuilder.append(")").append(GROUP_BY_BUCKET_Id).toString()
        }
    }

    /**
     * Query conditions in image modes
     *
     * @param queryMimeTypeOptions
     * @param fileSizeCondition
     * @return
     */
    private fun getSelectionArgsForImageMediaCondition(
        queryMimeTypeOptions: String,
        fileSizeCondition: String
    ): String {
        val stringBuilder = java.lang.StringBuilder()
        return if (SdkVersionUtils.checkedAndroid_Q()) {
            stringBuilder.append(MediaStore.Files.FileColumns.MEDIA_TYPE).append("=?")
                .append(queryMimeTypeOptions).append(" AND ").append(fileSizeCondition).toString()
        } else {
            stringBuilder.append("(").append(MediaStore.Files.FileColumns.MEDIA_TYPE).append("=?")
                .append(queryMimeTypeOptions).append(") AND ").append(fileSizeCondition).append(")")
                .append(GROUP_BY_BUCKET_Id).toString()
        }
    }

    /**
     * Video or Audio mode conditions
     *
     * @param queryMimeTypeOptions
     * @param fileSizeCondition
     * @return
     */
    private fun getSelectionArgsForVideoOrAudioMediaCondition(
        queryMimeTypeOptions: String,
        fileSizeCondition: String
    ): String {
        val stringBuilder = java.lang.StringBuilder()
        return if (SdkVersionUtils.checkedAndroid_Q()) {
            stringBuilder.append(MediaStore.Files.FileColumns.MEDIA_TYPE).append("=?")
                .append(queryMimeTypeOptions).append(" AND ").append(fileSizeCondition).toString()
        } else {
            stringBuilder.append("(").append(MediaStore.Files.FileColumns.MEDIA_TYPE).append("=?")
                .append(queryMimeTypeOptions).append(") AND ").append(fileSizeCondition).append(")")
                .append(GROUP_BY_BUCKET_Id).toString()
        }
    }


    private fun getSelectionArgs(): Array<String> {
        when (config.chooseMode) {
            PictureConfig.TYPE_ALL ->                 // Get all
                return getSelectionArgsForAllMediaType()
            PictureConfig.TYPE_IMAGE ->                 // Get photo
                return getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE)
            PictureConfig.TYPE_VIDEO ->                 // Get video
                return getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO)
            PictureConfig.TYPE_AUDIO ->                 // Get audio
                return getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_AUDIO)
        }
        return arrayOf()
    }

    /**
     * Gets a file of the specified type
     *
     * @return
     */
    private fun getSelectionArgsForAllMediaType(): Array<String> {
        return arrayOf(
            MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE.toString(),
            MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO.toString()
        )
    }

    /**
     * Gets a file of the specified type
     *
     * @param mediaType
     * @return
     */
    private fun getSelectionArgsForSingleMediaType(mediaType: Int): Array<String> {
        return arrayOf(mediaType.toString())
    }

    private fun getPageSelection(bucketId: Long): String? {
        val durationCondition = getDurationCondition()
        val sizeCondition = getFileSizeCondition()
        val queryMimeCondition = getQueryMimeCondition()
        when (config.chooseMode) {
            PictureConfig.TYPE_ALL ->                 //  Gets the all
                return getPageSelectionArgsForAllMediaCondition(
                    bucketId,
                    queryMimeCondition,
                    durationCondition,
                    sizeCondition
                )
            PictureConfig.TYPE_IMAGE ->                 // Gets the image of the specified type
                return getPageSelectionArgsForImageMediaCondition(
                    bucketId,
                    queryMimeCondition,
                    sizeCondition
                )
            PictureConfig.TYPE_VIDEO, PictureConfig.TYPE_AUDIO ->                 //  Gets the video or audio
                return getPageSelectionArgsForVideoOrAudioMediaCondition(
                    bucketId,
                    queryMimeCondition,
                    durationCondition,
                    sizeCondition
                )
        }
        return null
    }

    private fun getPageSelectionArgsForAllMediaCondition(
        bucketId: Long,
        queryMimeCondition: String,
        durationCondition: String,
        sizeCondition: String
    ): String? {
        val stringBuilder = java.lang.StringBuilder()
        stringBuilder.append("(").append(MediaStore.Files.FileColumns.MEDIA_TYPE)
            .append("=?").append(queryMimeCondition).append(" OR ")
            .append(MediaStore.Files.FileColumns.MEDIA_TYPE).append("=? AND ")
            .append(durationCondition).append(") AND ")
        return if (bucketId == -1L) {
            stringBuilder.append(sizeCondition).toString()
        } else {
            stringBuilder.append(COLUMN_BUCKET_ID).append("=? AND ")
                .append(sizeCondition).toString()
        }
    }

    private fun getPageSelectionArgsForImageMediaCondition(
        bucketId: Long,
        queryMimeCondition: String,
        sizeCondition: String
    ): String? {
        val stringBuilder = java.lang.StringBuilder()
        stringBuilder.append("(").append(MediaStore.Files.FileColumns.MEDIA_TYPE).append("=?")
        return if (bucketId == -1L) {
            stringBuilder.append(queryMimeCondition).append(") AND ").append(sizeCondition)
                .toString()
        } else {
            stringBuilder.append(queryMimeCondition).append(") AND ")
                .append(COLUMN_BUCKET_ID).append("=? AND ")
                .append(sizeCondition).toString()
        }
    }

    private fun getPageSelectionArgsForVideoOrAudioMediaCondition(
        bucketId: Long,
        queryMimeCondition: String,
        durationCondition: String,
        sizeCondition: String
    ): String? {
        val stringBuilder = java.lang.StringBuilder()
        stringBuilder.append("(").append(MediaStore.Files.FileColumns.MEDIA_TYPE).append("=?")
            .append(queryMimeCondition).append(" AND ").append(durationCondition).append(") AND ")
        return if (bucketId == -1L) {
            stringBuilder.append(sizeCondition).toString()
        } else {
            stringBuilder.append(COLUMN_BUCKET_ID).append("=? AND ")
                .append(sizeCondition).toString()
        }
    }

    private fun getPageSelectionArgs(bucketId: Long): Array<String> {
        when (config.chooseMode) {
            PictureConfig.TYPE_ALL -> {
                return if (bucketId == -1L) {
                    // ofAll
                    arrayOf(
                        MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE.toString(),
                        MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO.toString()
                    )
                } else arrayOf(
                    MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE.toString(),
                    MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO.toString(),
                    ValueOf.toString(bucketId)
                )
                //  Gets the specified album directory
            }
            PictureConfig.TYPE_IMAGE ->                 // Get photo
                return getSelectionArgsForPageSingleMediaType(
                    MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE,
                    bucketId
                )
            PictureConfig.TYPE_VIDEO ->                 // Get video
                return getSelectionArgsForPageSingleMediaType(
                    MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO,
                    bucketId
                )
            PictureConfig.TYPE_AUDIO ->                 // Get audio
                return getSelectionArgsForPageSingleMediaType(
                    MediaStore.Files.FileColumns.MEDIA_TYPE_AUDIO,
                    bucketId
                )
        }
        return arrayOf()
    }

    private fun getSelectionArgsForPageSingleMediaType(
        mediaType: Int,
        bucketId: Long
    ): Array<String> {
        return if (bucketId == -1L) arrayOf(mediaType.toString()) else arrayOf(
            mediaType.toString(),
            ValueOf.toString(bucketId)
        )
    }

    /**
     * Get cover uri
     *
     * @param cursor
     * @return
     */
    private fun getFirstUri(cursor: Cursor): String {
        val id = cursor.getLong(cursor.getColumnIndex(MediaStore.Files.FileColumns._ID))
        val mimeType =
            cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.MIME_TYPE))
        return PictureMimeType.getRealPathUri(id, mimeType)
    }

    /**
     * Get cover uri mimeType
     *
     * @param cursor
     * @return
     */
    private fun getFirstCoverMimeType(cursor: Cursor): String {
        return cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.MIME_TYPE))
    }

    /**
     * Get cover url
     *
     * @param cursor
     * @return
     */
    private fun getFirstUrl(cursor: Cursor): String {
        return cursor.getString(cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA))
    }

}